package com.bac.rentmap.osm;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.ServletContext;

import org.springframework.beans.factory.annotation.Required;

import com.bac.rentmap.ad.flat.LocalAddress;
import com.bac.rentmap.ad.flat.crawler.localaddress.LocalAddressParser;
import com.bac.rentmap.model.Building;
import com.google.appengine.api.datastore.GeoPt;

/**
 *
 * @author Ivan Holub
 */
public class BuildingsReader {
	private static final Logger log = Logger.getLogger(BuildingsReader.class
			.getName());

	private LocalAddressParser localAddressParser;
	private Pattern buildingPartPattern = Pattern
			.compile("(\\d+)(?:к(\\d+)|(\\p{L}+))?");

	public List<Building> readBuildings(ServletContext servletContext, String city) {
		return readBuildings(servletContext, 0, Integer.MAX_VALUE, city);
	}

	public List<Building> readBuildings(ServletContext servletContext,
			int startIndex, int maxCount, String city) {
		log.info("About to read " + maxCount + " buildings starting from "
				+ startIndex + " for " + city);

		InputStream is = servletContext
				.getResourceAsStream("/WEB-INF/osm/" + city + ".txt");
		List<Building> retValue = new ArrayList<Building>();
		try {
			BufferedReader br = new BufferedReader(new InputStreamReader(is,
					"utf-8"));
			String line;
			int i = 0;
			while ((line = br.readLine()) != null && i < startIndex + maxCount) {
				if (i++ >= startIndex) {
					Building b = new Building();
					try {
						String[] s = line.split("\t");
						float lat = Float.valueOf(s[0]);
						float lon = Float.valueOf(s[1]);
						b.setGeoPt(new GeoPt(lat, lon));
						LocalAddress localAddress = localAddressParser
								.parse(s[2]);
						parseBuildingNumber(localAddress, s[3]);
						b.setLocalAddress(localAddress);
						b.setCity(city);
						retValue.add(b);
					} catch (IllegalArgumentException e) {
						log.warning("Can't read building from line " + line
								+ ", because " + e.getMessage());
					}
				}

			}
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
		return retValue;
	}

	void parseBuildingNumber(LocalAddress localAddress, String string) {
		Matcher matcher = buildingPartPattern.matcher(string);
		boolean matchFound = matcher.find();
		if (matchFound) {
			localAddress.setBuilding(Integer.valueOf(matcher.group(1)));
			String buildingPart = matcher.group(2);
			if (buildingPart == null)
				buildingPart = matcher.group(3);
			localAddress.setBuildingPart(buildingPart);
		} else
			throw new IllegalArgumentException(
					"Can't parse building number from " + string);

	}

	@Required
	public void setLocalAddressParser(LocalAddressParser localAddressParser) {
		this.localAddressParser = localAddressParser;
	}
}
